package net.cathackers.devel.scmp.chat.interfaces;

import java.io.IOException;

import net.cathackers.devel.scmp.exceptions.NotAllowedException;
import net.cathackers.devel.scmp.xmpp.Packet;

import org.dom4j.Document;


public interface XMPPConnection {
    /****************
     * SOME Structures
     */
    enum CompressionPolicy {

        /**
         * compression is optional to interact with the server.
         */
        optional,

        /**
         * compression is not available. Entities that request a compression negotiation
         * will get a stream error and their connections will be closed.
         */
        disabled
    }
    /**
     * Enumeration of possible TLS policies required to interact with the server.
     */
    enum TLSPolicy {

        /**
         * TLS is required to interact with the server. Entities that do not secure their
         * connections using TLS will get a stream error and their connections will be closed.
         */
        required,

        /**
         * TLS is optional to interact with the server. Entities may or may not secure their
         * connections using TLS.
         */
        optional,

        /**
         * TLS is not available. Entities that request a TLS negotiation will get a stream
         * error and their connections will be closed.
         */
        disabled
    }
    /**
     * Enumeration that specifies if clients should be authenticated (and how) while
     * negotiating TLS.
     */
    enum ClientAuth {

        /**
         * No authentication will be performed on the client. Client credentials will not
         * be verified while negotiating TLS.
         */
        disabled,

        /**
         * Clients will try to be authenticated. Unlike 'needed', if the client
         * chooses not to provide authentication information about itself, the TLS negotiations
         * will stop and the connection will be dropped. This option is only useful for
         * engines in the server mode.
         */
        wanted,

        /**
         * Clients need to be authenticated. Unlike 'wanted', if the client
         * chooses not to provide authentication information about itself, the TLS negotiations
         * will continue. This option is only useful for engines in the server mode.
         */
        needed
    }
    /**
     * 
     * to validate if a connection is still alive or not, this is usually done
     * by sending white space.
     * @return boolean (true if alive, false if not)
     */
    public boolean heartBeat();
    /**
     * initialize the Connection with the user session object.
     * normally be ChatUserSession
     * @param session
     */
//    public void initialize(ChatSession session);
    public long getLastActive();
    public void setLastActive(long timestamp);
    
    /**
     * Close this session including associated socket connection. The order of
     * events for closing the session is:
     *  * Set closing flag to prevent redundant shutdowns.
     *  * Call notifyEvent all listeners that the channel is shutting down if we have that mechanism.
     *  * Close the socket.
     */
    public boolean isFlashClient();

    /**
     * Sets whether the connected client is a flash client. Flash clients need to
     * receive a special character (i.e. \0) at the end of each xml packet. Flash
     * clients may send the character \0 in incoming packets and may start a
     * connection using another opening tag such as: "flash:client".
     *
     * @param flashClient true if the if the connection is a flash client.
     */
    public void setFlashClient(boolean flashClient);
    
    public void close();
    public boolean isClosed();
    /**
     * Notification message indicating that the server is being shutdown. Implementations
     * should send a stream error whose condition is system-shutdown before closing
     * the connection.
     */
    public void systemShutdown();
    /**
     * Deliver Packet object to that user directy
     * @param packet
     * @throws NotAllowedException
     */
    public void deliver(Packet packet) throws NotAllowedException;
    /**
     * Deliver a DOM document directly to the client
     * @param packet
     * @throws NotAllowedException
     */
    public void deliver(Document packet) throws NotAllowedException;
    /**
     * Deliver a text input to the user...
     * @param text
     * @throws NotAllowedException
     */
    public void deliverString(String text);
    
    public int getMajorXMPPVersion();
    public int getMinorXMPPVersion();
    public void setXMPPVersion(int majorVersion, int minorVersion);
    public String getSessionID();
    public void setSessionID(String sessionID);
    
    public String getLanguage();
    public void setLanaguage(String language); //default is 'en'
    boolean isCompressed();
    CompressionPolicy getCompressionPolicy();
    void setCompressionPolicy(CompressionPolicy compressionPolicy);
    /**
     * Returns whether TLS is mandatory, optional or is disabled. When TLS is mandatory clients
     * are required to secure their connections or otherwise their connections will be closed.
     * On the other hand, when TLS is disabled clients are not allowed to secure their connections
     * using TLS. Their connections will be closed if they try to secure the connection. in this
     * last case.
     *
     * @return whether TLS is mandatory, optional or is disabled.
     */
    TLSPolicy getTLSPolicy();
    /**
     * Sets whether TLS is mandatory, optional or is disabled. When TLS is mandatory clients
     * are required to secure their connections or otherwise their connections will be closed.
     * On the other hand, when TLS is disabled clients are not allowed to secure their connections
     * using TLS. Their connections will be closed if they try to secure the connection. in this
     * last case.
     *
     * @param tlsPolicy whether TLS is mandatory, optional or is disabled.
     */
    void setTLSPolicy(TLSPolicy tlsPolicy);
    
    /**
     * Secures the plain connection by negotiating TLS with the other peer. In a server-2-server
     * connection the server requesting the TLS negotiation will be the client and the other server
     * will be the server during the TLS negotiation. Therefore, the server requesting the TLS
     * negotiation must pass 'true' in the 'clientMode' parameter and the server
     * receiving the TLS request must pass 'false' in the 'clientMode' parameter.
     * Both servers should specify the XMPP domain of the other server in the 'remoteServer'
     * parameter.
     *
     * In the case of client-2-server the XMPP server must pass 'false' in the
     * "clientMode" parameter since it will behave as the server in the TLS negotiation. The
     * "remoteServer" parameter will always be "null".
     *
     * @param clientMode boolean indicating if this entity is a client or a server in the TLS negotiation.
     * @param remoteServer xmpp domain of the remote server or "null". When null a
     *       'ClientTrustManager' will be used for verifying certificates
     *       otherwise there should be a 'ServerTrustManager' to verify servers //TODO to be implemented later.
     * @param authentication policy to use for authenticating the remote peer.
     * @throws IOException 
     * @throws Exception if an error occured while securing the connection.
     */
    void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception;
    boolean isTLS();
    /**
     * Adds the compression filter to the connection but only filter incoming traffic. Do not filter
     * outgoing traffic since we still need to send an uncompressed stanza to the client indicating
     * that he can start compressing the traffic. After we sent the uncompresses stanza we can
     * start compression outgoing traffic as well.
     */
    void addCompression();

    /**
     * Start compressing outgoing traffic for this connection. Compression will only be available after
     * TLS has been negotiated. This means that a connection can never be using compression before
     * TLS. However, it is possible to use compression without TLS but we are forcing using TLS by default
     * for security reasons.
     */
    void startCompression();

}
